/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xmijcoltrane;

/**
 *
 * @author Felipe Gutierrez
 */








import java.util.ArrayList;
import java.util.Stack;

import net.sf.jColtrane.annotations.methods.BeforeElement;
import net.sf.jColtrane.annotations.methods.EndElement;
import net.sf.jColtrane.annotations.methods.StartElement;
import net.sf.jColtrane.handler.AttributesHolder;
import net.sf.jColtrane.handler.ContextVariables;
import net.sf.jColtrane.handler.SAXEvent;


import xmibase.XmiPackage;
import xmibase.XmiAttribute;
import xmibase.XmiClass;
import xmibase.XmiDataType;
import xmibase.XmiGeneralization;
import xmibase.XmiInterface;
import xmibase.XmiPackage;

public class XmiBuilder {

	public ArrayList<XmiClass> classes;
	public ArrayList<XmiAttribute> attributes;

	public XmiPackage rootPackage;

	// public String currentClassName;
	// public Stack<String> currentAttName;
	public Stack elements;

	public XmiBuilder(XmiPackage packages, Stack element) {

		this.classes = new ArrayList<XmiClass>();
		this.attributes = new ArrayList<XmiAttribute>();

		this.elements = element;
		this.rootPackage = packages;
	}

	/**
	 * starts the tag UML:Package and gets the packages and build as the xmi
	 * file
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 1, tag = "UML:Namespace.ownedElement")
	@StartElement(tag = "UML:Package")
	public void startElementPackage(ContextVariables contextVariables) {

		SAXEvent event = contextVariables.getLastEvent();
		XmiPackage xmiPackage = new XmiPackage();
		if (this.elements.empty()) {

			System.out.println("Start Package: "
					+ event.getAtributesHolder().getValue("name"));

			xmiPackage.setName(event.getAtributesHolder().getValue("name"));
			xmiPackage.setId(event.getAtributesHolder().getValue("xmi.id"));

			this.elements.push(xmiPackage);
			this.rootPackage.addPackage(xmiPackage);

		} else {

			XmiPackage tmpParentPkg = (XmiPackage) this.elements.peek();

			xmiPackage.setName(event.getAtributesHolder().getValue("name"));
			xmiPackage.setId(event.getAtributesHolder().getValue("xmi.id"));

			System.out.println("Start Package: "
					+ xmiPackage.getName());

			tmpParentPkg.addPackage(xmiPackage);

			this.elements.push(xmiPackage);

			// this.rootPackage.addPackage(tmpParentPkg);

		}
		contextVariables.putInGeneralUseMap(xmiPackage.getId(), xmiPackage);

	}

	/**
	 * end of the tag UML:Package
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 1, tag = "UML:Namespace.ownedElement")
	@EndElement(tag = "UML:Package")
	public void endElementPackage(ContextVariables contextVariables) {
		SAXEvent event = contextVariables.getLastEvent();
		String namePackage = (String) event.getAtributesHolder().getValue(
				"name");
		if (!(this.elements.empty())) {
			this.elements.pop();
		}
		System.out.println("End Package: " + namePackage + "\n||||||");
	}

	// Elements of Package

	/**
	 * start UML:Class element to get the this element to UML:Package
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 1, tag = "UML:Namespace.ownedElement")
	@StartElement(tag = "UML:Class")
	public void startElementClass(ContextVariables contextVariables) {

		AttributesHolder attHolder = contextVariables.getLastEvent().getAtributesHolder();

		XmiClass classe = new XmiClass();

		System.out.println("	Start Class: "
				+ attHolder.getValue("name"));

		classe.setName(attHolder.getValue("name"));

		classe.setActive(Boolean.parseBoolean(attHolder.getValue("isActive")));
		classe.setLeaf(Boolean.parseBoolean(attHolder.getValue("isLeaf")));
		classe.setRoot(Boolean.parseBoolean(attHolder.getValue("isRoot")));
		classe.setSpecification(Boolean.parseBoolean(attHolder.getValue("isSpecification")));
		classe.setVisibility(attHolder.getValue("visibility"));

		classe.setId(attHolder.getValue("xmi.id"));

		this.elements.push(classe);


	}

	/**
	 * start UML:Class element to get the this element to UML:Package
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 2, tag = "UML:Package")
	@StartElement(tag = "UML:Interface")
	public void startElementInterface(ContextVariables contextVariables) {

		SAXEvent event = contextVariables.getLastEvent();
		XmiInterface xmiInterface = new XmiInterface();

		System.out.println("	Start Interface: "
				+ event.getAtributesHolder().getValue("name"));

		// set values of xmiClass

		xmiInterface.setName(event.getAtributesHolder().getValue("name"));
		xmiInterface.setId(event.getAtributesHolder().getValue("xmi.id"));

		XmiPackage tempPackage = (XmiPackage) this.elements.peek();

		tempPackage.addInterface(xmiInterface);

	}

	/**
	 * end of the UML:Class element, element of a UML:Package
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 1, tag = "UML:Namespace.ownedElement")
	@EndElement(tag = "UML:Class")
	public void endElementClass(ContextVariables contextVariables) {
		SAXEvent event = contextVariables.getLastEvent();
		// recebe a classe do mapa
		XmiClass tempClass = (XmiClass) this.elements.peek();
		// retira o id da classe do mapa

		this.elements.pop();
		// para cada atributo na lista, adiciona na classe

		// limpa os atributos
		this.attributes.clear();
		// se a pilha de tags estiver limpa adiciona no pacote raiz
		if (this.elements.empty()) {

			this.rootPackage.addClass(tempClass);

		} else {
			// se nao, recebe o pacote do mapa utilizando o id do pacote
			XmiPackage tempPackage = (XmiPackage) this.elements.peek();
			// adiciona a classe no pacote
			tempPackage.addClass(tempClass);

		}
		System.out.println("	End Class: "
				+ event.getAtributesHolder().getValue("name"));

		System.out.println("----------------------");
	}

	/**
	 * start UML:DataType element to get the this element to UML:Package
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 1, tag = "UML:Namespace.ownedElement")
	@StartElement(tag = "UML:DataType")
	public void startElementDataType(ContextVariables contextVariables) {

		SAXEvent event = contextVariables.getLastEvent();
		XmiDataType dataType = new XmiDataType();

		System.out.println("	Start DataType: "
				+ event.getAtributesHolder().getValue("name"));

		// set values of xmiClass

		dataType.setName(event.getAtributesHolder().getValue("name"));
		dataType.setId(event.getAtributesHolder().getValue("xmi.id"));

		this.elements.push(dataType);

	}

	/**
	 * end of the UML:DataType element, element of a UML:Package
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 1, tag = "UML:Namespace.ownedElement")
	@EndElement(tag = "UML:DataType")
	public void endElementDataType(ContextVariables contextVariables) {
		SAXEvent event = contextVariables.getLastEvent();

		XmiDataType tempDataType = (XmiDataType) this.elements.peek();
		this.elements.pop();

		if (this.elements.empty()) {

			this.rootPackage.addDataType(tempDataType);

		} else {
			Object obj = this.elements.peek();
			if (obj instanceof XmiPackage) {
				XmiPackage tempPackage = (XmiPackage) obj;
				tempPackage.addDataType(tempDataType);
			}
			if (obj instanceof XmiClass) {
				XmiClass tempClass = (XmiClass) obj;
				tempClass.addDataType(tempDataType);
			}
		}

		System.out.println("	End DataType: "
				+ event.getAtributesHolder().getValue("name"));
		// this.rootPackage.addClass(tempClass);

		// this.currentClassName = null;
		this.attributes = new ArrayList<XmiAttribute>();

		contextVariables = null;
		System.out.println("----------------------");
	}

	// Elements of Class





	/**
	 * UML:Generalization at UML:Class
	 *
	 * @param contextVariables
	 */
	@BeforeElement(elementDeep = 2, tag = "UML:Class")
	@EndElement(tag = "UML:Generalization")
	public void startGeneralization(ContextVariables contextVariables) {
		SAXEvent event = contextVariables.getLastEvent();

		System.out.println("		Start generalizable: " + event.getAtributesHolder().getValue("xmi.idref"));

		XmiGeneralization xmiGeneralization = new XmiGeneralization();

		xmiGeneralization.setId(event.getAtributesHolder()
				.getValue("xmi.idref"));

		Object obj = this.elements.peek();

		if (obj instanceof XmiClass) {
			XmiClass tmpXMIClass = (XmiClass) obj;

			tmpXMIClass.setHasSuperClass(true);
			tmpXMIClass.setGeneralization(xmiGeneralization);
		}
		System.out.println("		End generalizable");

	}

	// Get Types of Attributes






}
